#include "startup.h"
#include "std/vga.h"
#include "std/debug.h"
#include "kernel/irq.h"
#include "kernel/vma.h"
#include "kernel/time.h"
#include "dev/keyboard.h"
#include "kernel/page.h"
#include "kernel/heap.h"
#include "kernel/slab.h"
#include "fs/fs.h"

static void show_krnl_info(void)
{
	extern uint idle_thread_stack;

	vga_clear();
	printk("Views (viskrnl) %u.%u.%u.%u (build %u)\n",
		(__VIEWSVER >> 24) & 0xFF,
		(__VIEWSVER >> 16) & 0xFF,
		(__VIEWSVER >> 8) & 0xFF,
		__VIEWSVER & 0xFF,
		__VIEWSBLD);

	dbg_output3("idle_thd_stru: %X\n", idle_thread_stack);
	dbg_output3("page_root_dir: %X\n", page_root_dir);
	dbg_output3("end_of_kernel: %X\n\n", end_of_krnl_preoccupied_area);

	// debug output for system information
	dbg_output3("sys - total memory: %u KB\n", sys_config_data.total_memory);
	dbg_output3("sys - viskrnl size: %u\n", sys_config_data.kernel_size);
	dbg_output3("sys - swap size limit: %u\n\n", sys_config_data.swap_size_limit);
}

static void kernel_module_init(void)
{
	uint i;
	typedef int (*kernel_module_init_f)(void);
	extern kernel_module_init_f krnl_mod_init_list[];

	for (i = 0; krnl_mod_init_list[i]; ++i)
	{
		if (krnl_mod_init_list[i]())
			go32_die_endless();
	}
}

// we are not going to include
// proc.h since there is definition
// confliction
void global_init_proc_module(void);

void startup32(void)
{
	show_krnl_info();

	// init traps module
	global_init_irq_module();

	// init time module
	global_init_time_module();

	// init vma module
	// this must be earlier than page module
	// since page module refer to vma
	global_init_vma_module();

	// init page module
	global_init_page_module();

	// init heaps
	global_init_heap();

	// init kmem_cache module
	global_init_kmem_cache_module();

	// init proc module
	global_init_proc_module();

	// init keyboard module - rely on proc
	global_init_keyboard_module();

	// init fs module
	global_init_vfs_module();

	// init all kernel modules
	kernel_module_init();

	dbg_output2("startup32: system startup finished\n");
}
